"""
响应处理中间件
提供响应格式化、错误处理、数据脱敏和性能监控功能
"""
import json
import time
import traceback
from typing import Dict, Any, Optional, Union
from datetime import datetime
from loguru import logger

from utils.logger import Logger
from utils.exceptions import APIException, ErrorCode
from utils.config import Config


class ResponseFormatter:
    """响应格式化器"""
    
    def __init__(self):
        self.logger = Logger.get_logger(agent_name="response_formatter")
        self.config = Config()
        
        # 响应配置
        self.response_config = {
            "include_timestamp": True,
            "include_request_id": True,
            "include_version": True,
            "pretty_print": self.config.get("api.pretty_print", False),
            "compress_large_responses": self.config.get("api.compress_large_responses", True),
            "compression_threshold": self.config.get("api.compression_threshold", 1024),  # 1KB
            "max_response_size": self.config.get("api.max_response_size", 10 * 1024 * 1024),  # 10MB
            "default_page_size": self.config.get("api.default_page_size", 20),
            "max_page_size": self.config.get("api.max_page_size", 100)
        }
        
        self.logger.info("响应格式化器初始化完成")
    
    def format_success_response(self, data: Any = None, 
                              message: str = "success",
                              metadata: Optional[Dict[str, Any]] = None,
                              request_id: Optional[str] = None) -> Dict[str, Any]:
        """
        格式化成功响应
        
        Args:
            data: 响应数据
            message: 成功消息
            metadata: 元数据
            request_id: 请求ID
            
        Returns:
            格式化后的响应
        """
        response = {
            "success": True,
            "code": ErrorCode.SUCCESS.value,
            "message": message,
            "data": data
        }
        
        # 添加时间戳
        if self.response_config["include_timestamp"]:
            response["timestamp"] = datetime.now().isoformat()
        
        # 添加请求ID
        if self.response_config["include_request_id"] and request_id:
            response["request_id"] = request_id
        
        # 添加版本信息
        if self.response_config["include_version"]:
            response["version"] = self.config.get("api.version", "1.0.0")
        
        # 添加元数据
        if metadata:
            response["metadata"] = metadata
        
        return response
    
    def format_error_response(self, error: Union[str, Exception], 
                            error_code: Optional[ErrorCode] = None,
                            details: Optional[Dict[str, Any]] = None,
                            request_id: Optional[str] = None) -> Dict[str, Any]:
        """
        格式化错误响应
        
        Args:
            error: 错误信息或异常对象
            error_code: 错误代码
            details: 详细信息
            request_id: 请求ID
            
        Returns:
            格式化后的错误响应
        """
        # 处理异常对象
        if isinstance(error, APIException):
            error_code = error.error_code
            message = error.message
            details = error.details
        elif isinstance(error, Exception):
            error_code = error_code or ErrorCode.INTERNAL_ERROR
            message = str(error)
            # 开发模式下包含堆栈信息
            if self.config.get("debug", False):
                details = details or {}
                details["stack_trace"] = traceback.format_exc()
        else:
            error_code = error_code or ErrorCode.INTERNAL_ERROR
            message = str(error)
        
        response = {
            "success": False,
            "code": error_code.value if error_code else ErrorCode.INTERNAL_ERROR.value,
            "message": message,
            "data": None
        }
        
        # 添加时间戳
        if self.response_config["include_timestamp"]:
            response["timestamp"] = datetime.now().isoformat()
        
        # 添加请求ID
        if self.response_config["include_request_id"] and request_id:
            response["request_id"] = request_id
        
        # 添加版本信息
        if self.response_config["include_version"]:
            response["version"] = self.config.get("api.version", "1.0.0")
        
        # 添加详细信息
        if details:
            response["details"] = details
        
        return response
    
    def format_paginated_response(self, items: list, 
                                  total: int,
                                  page: int,
                                  page_size: int,
                                  message: str = "success",
                                  request_id: Optional[str] = None) -> Dict[str, Any]:
        """
        格式化分页响应
        
        Args:
            items: 数据项列表
            total: 总记录数
            page: 当前页码
            page_size: 每页大小
            message: 成功消息
            request_id: 请求ID
            
        Returns:
            格式化后的分页响应
        """
        # 计算分页信息
        total_pages = (total + page_size - 1) // page_size
        has_next = page < total_pages
        has_prev = page > 1
        
        # 构建分页数据
        data = {
            "items": items,
            "pagination": {
                "total": total,
                "page": page,
                "page_size": page_size,
                "total_pages": total_pages,
                "has_next": has_next,
                "has_prev": has_prev
            }
        }
        
        return self.format_success_response(
            data=data,
            message=message,
            request_id=request_id
        )
    
    def check_response_size(self, response_data: Dict[str, Any]) -> bool:
        """
        检查响应大小是否超出限制
        
        Args:
            response_data: 响应数据
            
        Returns:
            是否超出限制
        """
        try:
            response_json = json.dumps(response_data)
            size = len(response_json.encode('utf-8'))
            return size > self.response_config["max_response_size"]
        except Exception:
            return False
    
    def truncate_large_response(self, response_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        截断大型响应
        
        Args:
            response_data: 响应数据
            
        Returns:
            截断后的响应
        """
        # 如果数据是列表，只保留前N项
        if isinstance(response_data.get("data"), list):
            original_count = len(response_data["data"])
            response_data["data"] = response_data["data"][:100]  # 只保留前100项
            response_data["metadata"] = response_data.get("metadata", {})
            response_data["metadata"]["truncated"] = True
            response_data["metadata"]["original_count"] = original_count
            response_data["metadata"]["truncated_count"] = 100
        
        return response_data


class DataMasker:
    """数据脱敏器"""
    
    def __init__(self):
        self.logger = Logger.get_logger(agent_name="data_masker")
        self.config = Config()
        
        # 敏感字段配置
        self.sensitive_fields = {
            "password": {"mask": "full", "log_mask": True},
            "token": {"mask": "partial", "show_chars": 4, "log_mask": True},
            "secret": {"mask": "full", "log_mask": True},
            "key": {"mask": "partial", "show_chars": 4, "log_mask": True},
            "email": {"mask": "email", "log_mask": True},
            "phone": {"mask": "phone", "log_mask": True},
            "id_card": {"mask": "id_card", "log_mask": True},
            "credit_card": {"mask": "credit_card", "log_mask": True},
            "bank_account": {"mask": "bank_account", "log_mask": True}
        }
        
        # 自定义敏感字段模式
        self.custom_patterns = [
            (r'\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b', "credit_card"),  # 信用卡
            (r'\b[A-Za-z]{2}\d{6}\b', "id_card"),  # 身份证
            (r'\b\d{3}-\d{2}-\d{4}\b', "ssn"),  # 社保号
        ]
        
        self.logger.info("数据脱敏器初始化完成")
    
    def mask_data(self, data: Any, mask_type: str = "auto") -> Any:
        """
        脱敏数据
        
        Args:
            data: 需要脱敏的数据
            mask_type: 脱敏类型 (auto, full, partial, email, phone, etc.)
            
        Returns:
            脱敏后的数据
        """
        if isinstance(data, dict):
            return self._mask_dict(data, mask_type)
        elif isinstance(data, list):
            return [self.mask_data(item, mask_type) for item in data]
        elif isinstance(data, str):
            return self._mask_string(data, mask_type)
        else:
            return data
    
    def _mask_dict(self, data: Dict[str, Any], mask_type: str) -> Dict[str, Any]:
        """脱敏字典数据"""
        masked_data = {}
        
        for key, value in data.items():
            # 自动检测敏感字段
            field_mask_type = self._detect_field_type(key, mask_type)
            
            if field_mask_type:
                masked_data[key] = self._mask_value(value, field_mask_type)
            else:
                # 递归处理嵌套数据
                masked_data[key] = self.mask_data(value, mask_type)
        
        return masked_data
    
    def _detect_field_type(self, field_name: str, mask_type: str) -> Optional[str]:
        """检测字段类型"""
        if mask_type != "auto":
            return mask_type
        
        # 检查字段名是否包含敏感关键词
        field_name_lower = field_name.lower()
        
        for sensitive_field, config in self.sensitive_fields.items():
            if sensitive_field in field_name_lower:
                return sensitive_field
        
        # 检查自定义模式
        if isinstance(field_name, str):
            for pattern, field_type in self.custom_patterns:
                if re.search(pattern, field_name, re.IGNORECASE):
                    return field_type
        
        return None
    
    def _mask_value(self, value: Any, field_type: str) -> Any:
        """脱敏值"""
        config = self.sensitive_fields.get(field_type, {"mask": "full"})
        mask_type = config["mask"]
        
        if mask_type == "full":
            return "****" if isinstance(value, str) else "****"
        
        elif mask_type == "partial":
            show_chars = config.get("show_chars", 4)
            if isinstance(value, str) and len(value) > show_chars:
                return value[:show_chars] + "****"
            return "****"
        
        elif mask_type == "email":
            if isinstance(value, str) and "@" in value:
                parts = value.split("@")
                if len(parts) == 2:
                    username = parts[0]
                    if len(username) > 3:
                        masked_username = username[:2] + "****" + username[-1]
                    else:
                        masked_username = "****"
                    return f"{masked_username}@{parts[1]}"
            return "****@****.****"
        
        elif mask_type == "phone":
            if isinstance(value, str):
                # 移除非数字字符
                digits = re.sub(r'\D', '', value)
                if len(digits) >= 7:
                    return f"{digits[:3]}****{digits[-4:]}"
            return "****"
        
        elif mask_type == "id_card":
            if isinstance(value, str) and len(value) >= 15:
                return f"{value[:4]}****{value[-4:]}"
            return "****"
        
        elif mask_type == "credit_card":
            if isinstance(value, str):
                digits = re.sub(r'\D', '', value)
                if len(digits) >= 8:
                    return f"{digits[:4]}****{digits[-4:]}"
            return "****"
        
        elif mask_type == "bank_account":
            if isinstance(value, str) and len(value) >= 8:
                return f"{value[:4]}****{value[-4:]}"
            return "****"
        
        else:
            return "****"
    
    def _mask_string(self, value: str, mask_type: str) -> str:
        """脱敏字符串"""
        return self._mask_value(value, mask_type)
    
    def mask_for_logging(self, data: Any) -> Any:
        """为日志记录脱敏数据"""
        return self.mask_data(data, "auto")


class ResponseMiddleware:
    """响应中间件"""
    
    def __init__(self):
        self.logger = Logger.get_logger(agent_name="response_middleware")
        self.formatter = ResponseFormatter()
        self.masker = DataMasker()
        
        # 性能监控配置
        self.performance_config = {
            "enable_metrics": True,
            "slow_request_threshold": 1.0,  # 1秒
            "enable_cors": True,
            "cors_origins": ["*"],
            "cors_methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
            "cors_headers": ["Content-Type", "Authorization", "X-Request-ID"]
        }
        
        self.logger.info("响应中间件初始化完成")
    
    async def process_response(self, response_data: Dict[str, Any], 
                             request_info: Dict[str, Any]) -> Dict[str, Any]:
        """
        处理响应
        
        Args:
            response_data: 响应数据
            request_info: 请求信息
            
        Returns:
            处理后的响应
        """
        try:
            start_time = time.time()
            
            # 添加性能指标
            if self.performance_config["enable_metrics"]:
                response_data["_metrics"] = {
                    "processing_time": time.time() - start_time,
                    "timestamp": datetime.now().isoformat()
                }
            
            # 检查响应大小
            if self.formatter.check_response_size(response_data):
                self.logger.warning(f"响应数据过大，进行截断处理")
                response_data = self.formatter.truncate_large_response(response_data)
            
            # 脱敏处理
            if request_info.get("sensitive_data", False):
                response_data = self.masker.mask_data(response_data)
            
            # 记录响应日志（脱敏后）
            masked_data = self.masker.mask_for_logging(response_data)
            self.logger.debug(f"响应处理完成: {masked_data.get('code', 'unknown')}")
            
            return response_data
            
        except Exception as e:
            self.logger.error(f"响应处理失败: {str(e)}")
            return self.formatter.format_error_response(
                error="响应处理失败",
                error_code=ErrorCode.INTERNAL_ERROR,
                request_id=request_info.get("request_id")
            )
    
    def add_cors_headers(self, response_data: Dict[str, Any], 
                        origin: Optional[str] = None) -> Dict[str, Any]:
        """添加CORS头"""
        if not self.performance_config["enable_cors"]:
            return response_data
        
        # 这里应该添加CORS头到HTTP响应头中
        # 由于我们处理的是JSON数据，这里只是记录配置
        cors_config = {
            "Access-Control-Allow-Origin": origin or "*",
            "Access-Control-Allow-Methods": ", ".join(self.performance_config["cors_methods"]),
            "Access-Control-Allow-Headers": ", ".join(self.performance_config["cors_headers"])
        }
        
        # 在实际应用中，这些头应该添加到HTTP响应中
        response_data["_cors"] = cors_config
        
        return response_data